﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Common.Utlis;
using S7.Net.Types;

namespace Common.Utils.S7Help
{
    public static class S7BindValue
    {

        /// <summary>
        /// 将属性绑定到DB块
        /// </summary>
        /// <typeparam name="TViewModel">ViewModel</typeparam>
        /// <typeparam name="TDB">DB块类型</typeparam>
        /// <typeparam name="TDBProperty">DB块属性类型</typeparam>
        /// <param name="viewModel"></param>
        /// <param name="viewModelPrpertyName">viewModel属性名称</param>
        /// <param name="dbPropertyName">db块属性名称</param>
        /// <returns></returns>
        public static IDisposable BindDBValue<TViewModel, TDB, TDBProperty>(this TViewModel viewModel,
            string viewModelPrpertyName, string dbPropertyName) where TDB : BaseDB where TDBProperty : struct
        {
            Type viewModelType = viewModel.GetType();
            PropertyInfo propertyInfo = viewModelType.GetProperty(viewModelPrpertyName,
                BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);

            Type dbType = typeof(TDB);
            var accessorExtend =
                Delegate.CreateDelegate(typeof(Action<TViewModel, TDBProperty>), propertyInfo.GetSetMethod(true)) as
                    Action<TViewModel, TDBProperty>;
            string contract = $"{dbType.FullName}_{dbPropertyName}";
            return MessageAggregator<DataItem>.Subscribe(x => accessorExtend(viewModel, (TDBProperty)x.Value),
                contract);
        }

        /// <summary>
        /// 将属性绑定到DB块
        /// </summary>
        /// <typeparam name="TViewModel"></typeparam>
        /// <typeparam name="TDB"></typeparam>
        /// <typeparam name="TDBProperty"></typeparam>
        /// <param name="viewModel"></param>
        /// <param name="expressionVM"></param>
        /// <param name="expressionDB"></param>
        /// <returns></returns>
        public static IDisposable BindDBValue<TViewModel, TDB, TDBProperty>(this TViewModel viewModel,
            Expression<Func<TViewModel, TDBProperty>> expressionVM, Expression<Func<TDB, TDBProperty>> expressionDB)
            where TDB : BaseDB where TDBProperty : struct
        {
            string viewModelPropertyName = PropertyHelp.GetPropertyName(expressionVM);
            string dbPropertyName = PropertyHelp.GetPropertyName(expressionDB);
            return BindDBValue<TViewModel, TDB, TDBProperty>(viewModel, viewModelPropertyName, dbPropertyName);
        }

        /// <summary>
        /// 将属性绑定到DB块(适合属性和DB名称一致)
        /// </summary>
        /// <typeparam name="TViewModel"></typeparam>
        /// <typeparam name="TDB"></typeparam>
        /// <typeparam name="TDBProperty"></typeparam>
        /// <param name="viewModel"></param>
        /// <param name="expressionVM"></param>
        /// <returns></returns>
        public static IDisposable BindDBValue<TViewModel, TDB, TDBProperty>(this TViewModel viewModel,
            Expression<Func<TViewModel, TDBProperty>> expressionVM)
            where TDB : BaseDB where TDBProperty : struct
        {
            string viewModelPropertyName = PropertyHelp.GetPropertyName(expressionVM);
            string dbPropertyName = viewModelPropertyName;
            return BindDBValue<TViewModel, TDB, TDBProperty>(viewModel, viewModelPropertyName, dbPropertyName);
        }
    }
}

    
